1 /*
2 * The Apache Software License, Version 1.1
3 *
4 * Copyright (c) 2002 The Apache Software Foundation. All rights
5 * reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. The end-user documentation included with the redistribution,
20 * if any, must include the following acknowledgment:
21 * "This product includes software developed by the
22 * Apache Software Foundation (http://www.apache.org/)."
23 * Alternately, this acknowledgment may appear in the software itself,
24 * if and wherever such third-party acknowledgments normally appear.
25 *
26 * 4. The names "Apache" and "Apache Software Foundation" must
27 * not be used to endorse or promote products derived from this
28 * software without prior written permission. For written
29 * permission, please contact apache@apache.org.
30 *
31 * 5. Products derived from this software may not be called "Apache",
32 * nor may "Apache" appear in their name, without prior written
33 * permission of the Apache Software Foundation.
34 *
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46 * SUCH DAMAGE.
47 * ====================================================================
48 *
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Software Foundation. For more
51 * information on the Apache Software Foundation, please see
52 * <http://www.apache.org/>.
53 */
54 package net.sf.cglib.core;
55
56 import java.beans.*;
57 import java.lang.reflect.*;
58 import java.util.*;
59 import org.objectweb.asm.Type;
60
61 /***
62 * @version $Id: ReflectUtils.java,v 1.20 2004/02/11 18:32:35 baliuka Exp $
63 */
64 public class ReflectUtils {
65 private ReflectUtils() { }
66
67 private static final Map primitives = new HashMap(8);
68 private static final Map transforms = new HashMap(8);
69 private static final ClassLoader defaultLoader = ReflectUtils.class.getClassLoader();
70 private static Method DEFINE_CLASS;
71 private static final java.security.ProtectionDomain PROTECTION_DOMAIN;
72
73 static {
74
75 PROTECTION_DOMAIN = (java.security.ProtectionDomain)
76 java.security.AccessController.doPrivileged(
77 new java.security.PrivilegedAction() {
78 public Object run() {
79 return ReflectUtils.class.getProtectionDomain();
80 }
81 }
82 );
83
84 java.security.AccessController.doPrivileged(
85 new java.security.PrivilegedAction() {
86 public Object run() {
87
88 try {
89
90 DEFINE_CLASS = ClassLoader.class.getDeclaredMethod("defineClass", new Class[]{ String.class ,byte[].class, int.class, int.class,java.security.ProtectionDomain.class });
91 DEFINE_CLASS.setAccessible(true);
92
93 } catch (NoSuchMethodException e) {
94 throw new CodeGenerationException(e);
95 }
96 return null;
97 }
98 }
99 );
100 }
101
102 private static final String[] CGLIB_PACKAGES = {
103 "java.lang",
104 };
105
106 static {
107 primitives.put("byte", Byte.TYPE);
108 primitives.put("char", Character.TYPE);
109 primitives.put("double", Double.TYPE);
110 primitives.put("float", Float.TYPE);
111 primitives.put("int", Integer.TYPE);
112 primitives.put("long", Long.TYPE);
113 primitives.put("short", Short.TYPE);
114 primitives.put("boolean", Boolean.TYPE);
115
116 transforms.put("byte", "B");
117 transforms.put("char", "C");
118 transforms.put("double", "D");
119 transforms.put("float", "F");
120 transforms.put("int", "I");
121 transforms.put("long", "J");
122 transforms.put("short", "S");
123 transforms.put("boolean", "Z");
124 }
125
126 public static Type[] getExceptionTypes(Member member) {
127 if (member instanceof Method) {
128 return TypeUtils.getTypes(((Method)member).getExceptionTypes());
129 } else if (member instanceof Constructor) {
130 return TypeUtils.getTypes(((Constructor)member).getExceptionTypes());
131 } else {
132 throw new IllegalArgumentException("Cannot get exception types of a field");
133 }
134 }
135
136 public static Signature getSignature(Member member) {
137 if (member instanceof Method) {
138 return new Signature(member.getName(), Type.getMethodDescriptor((Method)member));
139 } else if (member instanceof Constructor) {
140 Type[] types = TypeUtils.getTypes(((Constructor)member).getParameterTypes());
141 return new Signature(Constants.CONSTRUCTOR_NAME,
142 Type.getMethodDescriptor(Type.VOID_TYPE, types));
143
144 } else {
145 throw new IllegalArgumentException("Cannot get signature of a field");
146 }
147 }
148
149 public static Constructor findConstructor(String desc) {
150 return findConstructor(desc, defaultLoader);
151 }
152
153 public static Constructor findConstructor(String desc, ClassLoader loader) {
154 try {
155 int lparen = desc.indexOf('(');
156 String className = desc.substring(0, lparen).trim();
157 return getClass(className, loader).getConstructor(parseTypes(desc, loader));
158 } catch (ClassNotFoundException e) {
159 throw new CodeGenerationException(e);
160 } catch (NoSuchMethodException e) {
161 throw new CodeGenerationException(e);
162 }
163 }
164
165 public static Method findMethod(String desc) {
166 return findMethod(desc, defaultLoader);
167 }
168
169 public static Method findMethod(String desc, ClassLoader loader) {
170 try {
171 int lparen = desc.indexOf('(');
172 int dot = desc.lastIndexOf('.', lparen);
173 String className = desc.substring(0, dot).trim();
174 String methodName = desc.substring(dot + 1, lparen).trim();
175 return getClass(className, loader).getDeclaredMethod(methodName, parseTypes(desc, loader));
176 } catch (ClassNotFoundException e) {
177 throw new CodeGenerationException(e);
178 } catch (NoSuchMethodException e) {
179 throw new CodeGenerationException(e);
180 }
181 }
182
183 private static Class[] parseTypes(String desc, ClassLoader loader) throws ClassNotFoundException {
184 int lparen = desc.indexOf('(');
185 int rparen = desc.indexOf(')', lparen);
186 List params = new ArrayList();
187 int start = lparen + 1;
188 for (;;) {
189 int comma = desc.indexOf(',', start);
190 if (comma < 0) {
191 break;
192 }
193 params.add(desc.substring(start, comma).trim());
194 start = comma + 1;
195 }
196 if (start < rparen) {
197 params.add(desc.substring(start, rparen).trim());
198 }
199 Class[] types = new Class[params.size()];
200 for (int i = 0; i < types.length; i++) {
201 types[i] = getClass((String)params.get(i), loader);
202 }
203 return types;
204 }
205
206 private static Class getClass(String className, ClassLoader loader) throws ClassNotFoundException {
207 return getClass(className, loader, CGLIB_PACKAGES);
208 }
209
210 private static Class getClass(String className, ClassLoader loader, String[] packages) throws ClassNotFoundException {
211 String save = className;
212 int dimensions = 0;
213 int index = 0;
214 while ((index = className.indexOf("[]", index) + 1) > 0) {
215 dimensions++;
216 }
217 StringBuffer brackets = new StringBuffer(className.length() - dimensions);
218 for (int i = 0; i < dimensions; i++) {
219 brackets.append('[');
220 }
221 className = className.substring(0, className.length() - 2 * dimensions);
222
223 String prefix = (dimensions > 0) ? brackets + "L" : "";
224 String suffix = (dimensions > 0) ? ";" : "";
225 try {
226 return Class.forName(prefix + className + suffix, false, loader);
227 } catch (ClassNotFoundException ignore) { }
228 for (int i = 0; i < packages.length; i++) {
229 try {
230 return Class.forName(prefix + packages[i] + '.' + className + suffix, false, loader);
231 } catch (ClassNotFoundException ignore) { }
232 }
233 if (dimensions == 0) {
234 Class c = (Class)primitives.get(className);
235 if (c != null) {
236 return c;
237 }
238 } else {
239 String transform = (String)transforms.get(className);
240 if (transform != null) {
241 try {
242 return Class.forName(brackets + transform, false, loader);
243 } catch (ClassNotFoundException ignore) { }
244 }
245 }
246 throw new ClassNotFoundException(save);
247 }
248
249
250 public static Object newInstance(Class type) {
251 return newInstance(type, Constants.EMPTY_CLASS_ARRAY, null);
252 }
253
254 public static Object newInstance(Class type, Class[] parameterTypes, Object[] args) {
255 return newInstance(getConstructor(type, parameterTypes), args);
256 }
257
258 public static Object newInstance(final Constructor cstruct, final Object[] args) {
259
260 boolean flag = cstruct.isAccessible();
261 try {
262 cstruct.setAccessible(true);
263 Object result = cstruct.newInstance(args);
264 return result;
265 } catch (InstantiationException e) {
266 throw new CodeGenerationException(e);
267 } catch (IllegalAccessException e) {
268 throw new CodeGenerationException(e);
269 } catch (InvocationTargetException e) {
270 throw new CodeGenerationException(e.getTargetException());
271 } finally {
272 cstruct.setAccessible(flag);
273 }
274
275 }
276
277 public static Constructor getConstructor(Class type, Class[] parameterTypes) {
278 try {
279 return type.getConstructor(parameterTypes);
280 } catch (NoSuchMethodException e) {
281 throw new CodeGenerationException(e);
282 }
283 }
284
285 public static Class[] getClasses(Object[] objects) {
286 Class[] classes = new Class[objects.length];
287 for (int i = 0; i < objects.length; i++) {
288 classes[i] = objects[i].getClass();
289 }
290 return classes;
291 }
292
293 public static Method findNewInstance(Class iface) {
294 Method m = findInterfaceMethod(iface);
295 if (!m.getName().equals("newInstance")) {
296 throw new IllegalArgumentException(iface + " missing newInstance method");
297 }
298 return m;
299 }
300
301 public static Method[] getPropertyMethods(PropertyDescriptor[] properties, boolean read, boolean write) {
302 Set methods = new HashSet();
303 for (int i = 0; i < properties.length; i++) {
304 PropertyDescriptor pd = properties[i];
305 if (read) {
306 methods.add(pd.getReadMethod());
307 }
308 if (write) {
309 methods.add(pd.getWriteMethod());
310 }
311 }
312 methods.remove(null);
313 return (Method[])methods.toArray(new Method[methods.size()]);
314 }
315
316 public static PropertyDescriptor[] getBeanProperties(Class type) {
317 return getPropertiesHelper(type, true, true);
318 }
319
320 public static PropertyDescriptor[] getBeanGetters(Class type) {
321 return getPropertiesHelper(type, true, false);
322 }
323
324 public static PropertyDescriptor[] getBeanSetters(Class type) {
325 return getPropertiesHelper(type, false, true);
326 }
327
328 private static PropertyDescriptor[] getPropertiesHelper(Class type, boolean read, boolean write) {
329 try {
330 BeanInfo info = Introspector.getBeanInfo(type, Object.class);
331 PropertyDescriptor[] all = info.getPropertyDescriptors();
332 if (read && write) {
333 return all;
334 }
335 List properties = new ArrayList(all.length);
336 for (int i = 0; i < all.length; i++) {
337 PropertyDescriptor pd = all[i];
338 if ((read && pd.getReadMethod() != null) ||
339 (write && pd.getWriteMethod() != null)) {
340 properties.add(pd);
341 }
342 }
343 return (PropertyDescriptor[])properties.toArray(new PropertyDescriptor[properties.size()]);
344 } catch (IntrospectionException e) {
345 throw new CodeGenerationException(e);
346 }
347 }
348
349
350
351 public static Method findDeclaredMethod(final Class type,
352 final String methodName, final Class[] parameterTypes)
353 throws NoSuchMethodException {
354
355 Class cl = type;
356 while (cl != null) {
357 try {
358 return cl.getDeclaredMethod(methodName, parameterTypes);
359 } catch (NoSuchMethodException e) {
360 cl = cl.getSuperclass();
361 }
362 }
363 throw new NoSuchMethodException(methodName);
364
365 }
366
367 public static List addAllMethods(final Class type, final List list) {
368
369
370 list.addAll(java.util.Arrays.asList(type.getDeclaredMethods()));
371 Class superclass = type.getSuperclass();
372 if (superclass != null) {
373 addAllMethods(superclass, list);
374 }
375 Class[] interfaces = type.getInterfaces();
376 for (int i = 0; i < interfaces.length; i++) {
377 addAllMethods(interfaces[i], list);
378 }
379
380 return list;
381 }
382
383 public static List addAllInterfaces(Class type, List list) {
384 Class superclass = type.getSuperclass();
385 if (superclass != null) {
386 list.addAll(Arrays.asList(type.getInterfaces()));
387 addAllInterfaces(superclass, list);
388 }
389 return list;
390 }
391
392
393 public static Method findInterfaceMethod(Class iface) {
394 if (!iface.isInterface()) {
395 throw new IllegalArgumentException(iface + " is not an interface");
396 }
397 Method[] methods = iface.getDeclaredMethods();
398 if (methods.length != 1) {
399 throw new IllegalArgumentException("expecting exactly 1 method in " + iface);
400 }
401 return methods[0];
402 }
403
404 public static Class defineClass(String className, byte[] b, ClassLoader loader) throws Exception {
405 Object[] args = new Object[]{className, b, new Integer(0), new Integer(b.length), PROTECTION_DOMAIN };
406 return (Class)DEFINE_CLASS.invoke(loader, args);
407 }
408
409 public static int findPackageProtected(Class[] classes) {
410 for (int i = 0; i < classes.length; i++) {
411 if (!Modifier.isPublic(classes[i].getModifiers())) {
412 return i;
413 }
414 }
415 return 0;
416 }
417 }
This page was automatically generated by Maven